#include <iostream>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
#include <sys/wait.h>

using namespace std;

const char *dev = "/dev/dmadriver";
void *ptr = NULL;
const int MEM_SIZE = 1024 * 1024;
int fd = -1;

int map()
{
    if (fd >= 0)
    {
        ptr = mmap(NULL, MEM_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
        if (ptr == MAP_FAILED)
        {
            cout << "Failed to mmap" << endl;
            return -1;
        }
    }
    else
    {
        cout << "Failed to open " << dev << endl;
        return -1;
    }
    return 0;
}

void unmap()
{
    munmap(ptr, MEM_SIZE);
}

void test1()
{
    map();

    // write
    for (int i = 0; i < MEM_SIZE; i++)
    {
        ((char *)ptr)[i] = i & 0x7f;
    }

    // read
    for (int i = 0; i < MEM_SIZE; i++)
    {
        if (((char *)ptr)[i] != (i & 0x7f))
        {
            cout << "Failed to verify, i = " << i << endl;
        }
    }

    unmap();
    cout << "test1 done" << endl;
}

void test2()
{
    // 创建子进程
    pid_t pid = fork();
    if (pid < 0)
    {
        cout << "Failed to fork" << endl;
        return;
    }
    if (pid > 0)
    {
        // 父进程
        map();
        cout << "Parent process" << endl;
        sleep(1);
        for (int i = 0; i < MEM_SIZE; ++i)
        {
            ((char *)ptr)[i] = i & 0x3f;
        }
        sleep(1);
        waitpid(pid, NULL, 0);
        unmap();
        cout << "test2 done" << endl;
    }
    else
    {
        // 子进程
        map();
        cout << "Child process" << endl;
        sleep(2);
        for (int i = 0; i < MEM_SIZE; ++i)
        {
            if (((char *)ptr)[i] != (i & 0x3f))
            {
                cout << "Failed to verify, i = " << i << endl;
            }
        }
        unmap();
    }
}

int main(int argc, char **argv)
{
    fd = open(dev, O_RDWR);
    if (fd < 0)
    {
        cout << "Failed to open " << dev << endl;
        return -1;
    }

    test1();
    test2();

    close(fd);
    return 0;
}
